AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')

local DESTROYABLE=true -- set to false to prevent damage
local FLAMETRAIL=false -- set to true for the old flame trail
local HOVERMODE=true -- set to true to hover instead of drop when shift is held

-- Onboard Storage tanks
local maximumNaquadah 	= 350
local maximumEnergy 		= 7000
local maximumCoolant 		= 3000
local maximumWater 		= 3500
local maximumAir 		= 3500

-- Fuel Consumption
local MinFuel = 50
local w = nil
local l = nil
local s = nil

local Loop_Sound = 'ambient/atmosphere/undercity_loop1.wav'

function ENT:SpawnFunction( ply, tr)
	local SpawnPos = tr.HitPos + tr.HitNormal * 100
	local ent = ents.Create( "spawnable_shuttle", "Refined Naquadah", "Energy", "Coolant", "Water", "Air" )
	
	if (ent:GetModel() != nil) then
		--nothing
	else
		ent:SetModel("models/props_combine/headcrabcannister01a.mdl")
	end

	ent:SetPos( SpawnPos )
	ent:Spawn()
	ent:Activate()

	return ent
end

function ENT:Initialize()
	self:SetPower( GetConVarNumber("shuttle_power")  )
	self:SetLife( GetConVarNumber("shuttle_life")  )
	self:SetSpeed( GetConVarNumber("shuttle_speed")  )

	self.MinFuel = MinFuel

	self.maxNaquadah 	= maximumNaquadah 
	self.maxEnergy 	= maximumEnergy 
	self.maxCoolant 	= maximumCoolant 
	self.maxWater 	= maximumWater 
	self.maxAir 	= maximumAir 	

	local maxNaquadah 	= self.maxNaquadah*self.powerrate+self.maxNaquadah/5
	local maxEnergy 	= self.maxEnergy*self.powerrate+self.maxEnergy/5
	local maxCoolant 	= self.maxCoolant*self.powerrate+self.maxCoolant/2
	local maxWater 	= self.maxWater*self.powerrate+self.maxWater/5
	local maxAir 	= self.maxAir*self.powerrate+self.maxAir/5
		
	self.percent = 50
	self.Entity:SetNWBool("hovermodeon", false)

	self.Naquadah = 0
	self.Energy = 0
	self.Coolant = 0
	self.Water = 0
	self.Air = 0

	self.active = 1

	self.lifeadd = 0
	self.rtickrate = 0.5
	self.utickrate = 0.05
	self.rrate = 0
	self.crate = 0

	self.Entity:Reset()

	if GetConVarNumber("shuttle_turn") == 1 then
		self.turn = -1
	else
		self.turn = 1
	end

	if ( GetConVarNumber("shuttle_roll")==1 ) then
		self.enableroll = 1
	else
		self.enableroll = 0
	end

	self.isinuse = 0
	self.Stopall = 0
	
	self.Entity:SetUseType( SIMPLE_USE )

	self.Firee=nil
	self.Inflight=false
	self.Pilot=nil

	self.Entity:PhysicsInit( SOLID_VPHYSICS )
	self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
	self.Entity:SetSolid( SOLID_VPHYSICS )
		local phys = self.Entity:GetPhysicsObject()
		if (!Loop_Sound) then
			Loop_Sound = 'ambient/atmosphere/undercity_loop1.wav'
		end
		if (!self.Sound) then
			self.Sound = CreateSound( self.Entity, Loop_Sound )
		end		
		if (!self.passive) then
			self.passive = 0
		end
		if (phys:IsValid()) then
			phys:Wake()
			phys:SetMass(self.weight)
		end
	self.Entity:StartMotionController()
	self.Accel=0
	self.Roll=0
	self.R = 0
	if not ( RES_DISTRIB == 2 ) then 
		Error("Please Install Resource Distribution 2 Addon.'" )
	end
	if (GetConVarNumber("shuttle_sv_rd_force_disable")==1) then
		--none
	else
		RD_AddResource(self.Entity, "Refined Naquadah", maxNaquadah)
		RD_AddResource(self.Entity, "energy", maxEnergy)
		RD_AddResource(self.Entity, "coolant", maxCoolant)
		RD_AddResource(self.Entity, "water", maxWater)
		RD_AddResource(self.Entity, "air", maxAir)
	end

	self.Inputs = Wire_CreateInputs(self.Entity, { "On","Hover" })
	self.Outputs = Wire_CreateOutputs(self.Entity, { "Refined Naquadah","Energy","Coolant","Water","Air","Consuming","Reload","Hover","Active","Movement","Speed","Turbo","Roll","Left","Right","Health" })
end

function ENT:Think()
	self.baseconsumerate = GetConVarNumber("shuttle_sv_rd_consumerate")

	if self.Sound then 
		self.percent = math.min(self.percent + 2, 100)
	else
		self.percent = math.max(self.percent - 2, 60)
	if self.percent < 61 then self.Sound:Stop() end
	end

	self.Sound:ChangePitch( self.percent );

	if (self.Stopall > 0) then return end
--[[ Wire outputs + RD support --]]
		self.velocity = self.Entity:GetVelocity():Length()
		self.consume = self.moveconsume+self.hoverconsume+self.rollconsume+self.repairconsume
		self.consumerate = self.powerrate*self.liferate*self.speedrate*self.baseconsumerate+self.baseconsumerate*2
		self.lifeadd = self.powerrate+self.liferate*2
		if (GetConVarNumber("shuttle_sv_rd_use")==1 and GetConVarNumber("shuttle_sv_rd_force_disable")==0) then
			self.Naquadah = RD_GetResourceAmount(self.Entity, "Refined Naquadah")
			self.Energy = RD_GetResourceAmount(self.Entity, "energy")
			self.Coolant = RD_GetResourceAmount(self.Entity, "coolant")
			self.Water = RD_GetResourceAmount(self.Entity, "water")
			self.Air = RD_GetResourceAmount(self.Entity, "air")
		else
			self.Naquadah = self.Naquadah 
			self.Energy = self.Energy
			self.Coolant = self.Coolant 
			self.Water = self.Water 
			self.Air = self.Air 
		end
		Wire_TriggerOutput(self.Entity, "Refined Naquadah", self.Naquadah) 
		Wire_TriggerOutput(self.Entity, "Energy", self.Energy)  
		Wire_TriggerOutput(self.Entity, "Coolant", self.Coolant) 
		Wire_TriggerOutput(self.Entity, "Water", self.Water) 
		Wire_TriggerOutput(self.Entity, "Air", self.Air)
		Wire_TriggerOutput(self.Entity, "Active", self.active)
		Wire_TriggerOutput(self.Entity, "Consuming", self.consume)
		Wire_TriggerOutput(self.Entity, "Reload", self.R)
		Wire_TriggerOutput(self.Entity, "Hover", self.hover)
		Wire_TriggerOutput(self.Entity, "Movement", self.moverate)
		Wire_TriggerOutput(self.Entity, "Speed", self.velocity)
		Wire_TriggerOutput(self.Entity, "Turbo", self.turbo-1)
		Wire_TriggerOutput(self.Entity, "Roll", self.roll)
		Wire_TriggerOutput(self.Entity, "Left", self.A)
		Wire_TriggerOutput(self.Entity, "Right", self.D)
		Wire_TriggerOutput(self.Entity, "Health", self.life)
	--self:SetOverlayText( "Shuttle\nEnergy: " .. self.Energy)
--]]---Wire------------------------
	if not ValidEntity(self.Pilot) then self.Pilot=nil self.Inflight=false end
	if self.Inflight and self.Pilot and self.Pilot:IsValid() then
		self.Pilot:SetPos(self.Entity:GetPos())
		if self.Pilot:KeyDown(IN_USE) then
			self.isinuse = 0

			self.Sound:Stop()

			self.Pilot:UnSpectate()
			self.Pilot:DrawViewModel(true)
			self.Pilot:DrawWorldModel(true)
			self.Pilot:Spawn()
			self.Pilot:SetNetworkedBool("isDriveShuttle",false)
			self.Pilot:SetPos(self.Entity:GetPos()+Vector(0,0,100))

			self.Accel=0
			self.Inflight=false
			if self.Firee then
				self.Firee:Remove()
			end
			self.Entity:SetLocalVelocity(Vector(0,0,0))
			self.Pilot=nil
		end	
		self.Entity:NextThink(CurTime())
	else
		self.Entity:NextThink(CurTime()+0.5)
	end
	return true
end

function ENT:TriggerInput(iname, value)
	if (iname == "On") then
		if GetConVarNumber("shuttle_aactive") == 1 then
			self.active = 1
		else
			if (value > 0) then
				self.active = 1
			else
				self.active = 0
			end
		end
	end
	if (iname == "Hover") then
		if (value > 0) then
			self.ihover = 1
		else
			self.ihover = 0
		end
	end
end

function ENT:PhysicsUpdate( physobj )
	if self.percent > 99 then
		local soundvel = self.Entity:GetVelocity():Length()
		if soundvel > 900 then soundvel = 900  end
		self.Sound:ChangePitch( 100 + (soundvel/6));
	end
end

function ENT:UpdateTransmitState() return TRANSMIT_ALWAYS end;

function ENT:PhysicsSimulate( phys, deltatime )
	local hovering=false	
	if self.Inflight then
		if self.active==0 then return end
	--	Wire // RD2
		if ( self.R==1 and self.life+self.lifeadd<=self.maxlife and self.rrate<=CurTime() and self.Energy >= (self.MinFuel*self.powerrate+self.MinFuel) ) then
			self.repairconsume = 3*self.consumerate
			if self.life+self.lifeadd >= self.maxlife then
				self.life=self.maxlife
				self.rrate = CurTime() + self.rtickrate
			else
				self.life=self.life+self.lifeadd
				self.rrate = CurTime() + self.rtickrate
				RD_ConsumeResource(self.Entity, "energy", self.repairconsume)
				self.Entity:Reset()
			end
			return
	 	end		
		if (GetConVarNumber("shuttle_sv_rd_use")==1 and GetConVarNumber("shuttle_sv_rd_force_disable")==0) then
			if (self.Energy >= (self.MinFuel*self.powerrate+self.MinFuel) ) then 
				self.Sound:Play()
				self.Sound:ChangePitch( self.percent );
				if self.crate<CurTime() then
					self.crate = CurTime() + self.utickrate
					RD_ConsumeResource(self.Entity, "energy", self.consume)
					return
				end
			else
				self.Sound:Stop()
				self.Entity:Reset()
				return
			end
		else
			self.Sound:Play()
			self.Sound:ChangePitch( self.percent );
		end

		if self.Pilot:KeyDown(IN_RELOAD) then
			self.R = 1
		else
			self.R = 0
		end

 		if self.ihover==1 or self.Pilot:KeyDown(IN_SPEED) then
			self.hover = 1
		else
			self.hover = 0
		end

		if self.Pilot:KeyDown(IN_MOVELEFT) then
			self.A=1
		else
			self.A=0
		end

		if self.Pilot:KeyDown(IN_MOVERIGHT) then
			self.D=1
		else
			self.D=0
		end

		if (GetConVarNumber("shuttle_ahover")==1) then
			hovering=true
			self.hoverconsume = 0.25*self.consumerate
		elseif HOVERMODE and self.hover==1 then
			hovering=true
			self.hoverconsume = 0.5*self.consumerate
		else
			hovering=false
			self.hoverconsume = 0
		end

		self.Entity:SetNetworkedBool("hover",hovering)
		self.num=0

		if self.Pilot:KeyDown(IN_ATTACK) then
			self.num=500
			self.turbo = 1
			self.moverate = 1
			self.moveconsume = 1*self.consumerate
		elseif self.Pilot:KeyDown(IN_ATTACK2) then
			self.num=-500 
			self.turbo = 1
			self.moverate = -1
			self.moveconsume = 1*self.consumerate
		elseif self.Pilot:KeyDown(IN_FORWARD) then
			self.num=2000
			self.turbo = 2
			self.moverate = 2
			self.moveconsume = 5*self.consumerate
		else
			self.turbo = 1
			self.moverate = 0
			self.moveconsume = 0
		end
		
		if self.Pilot:KeyDown(IN_MOVELEFT) then
			self.Roll = self.Roll-1*self.enableroll/self.powerrate*self.speedrate/1.5
			self.rollconsume = 0.125*self.consumerate
			self.roll = -1
		elseif self.Pilot:KeyDown(IN_MOVERIGHT) then
			self.Roll = self.Roll+1*self.enableroll/self.powerrate*self.speedrate/1.5
			self.rollconsume = 0.125*self.consumerate
			self.roll = 1
		else
			self.rollconsume = 0
			self.roll = 0
		end

		phys:Wake()

		self.Accel = math.Approach(self.Accel,self.num*self.speedrate,10)
		if self.Accel > -200 and self.Accel < 200 and not self.Pilot:KeyDown(IN_ATTACK) and not self.Pilot:KeyDown(IN_ATTACK2) and not self.Pilot:KeyDown(IN_FORWARD) and not hovering then return end
		local pr={}

--	Wire // RD2
			pr.secondstoarrive	= 1
			pr.pos				= self.Entity:GetPos()+self.Entity:GetForward()*self.Accel*self.turn
			pr.maxangular	= 1000--*self.speedrate/self.turbo
			pr.maxangulardamp	= 1000--*self.speedrate/self.turbo
			pr.maxspeed	= 1000--*self.speedrate*self.turbo
			pr.maxspeeddamp	= 10000--*self.speedrate*self.turbo
			pr.dampfactor	= 0.8
			pr.teleportdistance	= 5000
				local ang = self.Pilot:GetAimVector():Angle()
				--local pang = angx.p
				--local yang = angx.y
				--local rang = angx.r
				ang.r=ang.r+self.Roll
			pr.angle			= ang
			--if self.Pilot:KeyDown(IN_SPEED) then
				--if HOVERMODE and self.num>0 then
					--pr.angle=self.Entity:GetAngles()
				--elseif not HOVERMODE then
					--pr.angle=self.Entity:GetAngles()
				--end
			--end
			pr.deltatime		= deltatime
		phys:ComputeShadowControl(pr)
	else
		self.Entity:Reset()
	end
end

function ENT:Reset()
	self.roll = 0
	self.A=0
	self.D=0
	self.consumerate = 0
	self.turbo = 1
	self.moverate = 0
	self.roll = 0
	self.hover = 0
	self.consume = 0
	self.rollconsume = 0
	self.hoverconsume = 0
	self.moveconsume = 0	
	self.repairconsume = 0
end

function ENT:SetPower( w )
	self.spower = w
	self.weight = self.spower/10
	self.bpower = 10000
	self.powerrate = self.spower/self.bpower
end

function ENT:SetLife( l )
	self.life = l
	self.maxlife = l
	self.blife = 500
	self.liferate = self.life/self.blife
end

function ENT:SetSpeed( s )
	self.sspeed = s
	self.speed = self.sspeed/2
	self.bspeed = 100
	self.speedrate = self.speed/self.bspeed
end

function ENT:DoKill()
	self.Stopall = 1

	if (self.Sound) then
		self.Sound:Stop()
	end

	if (self.isinuse>0) then
		self.Value = 0
		self.Pilot:UnSpectate()
		self.Pilot:DrawViewModel(true)
		self.Pilot:DrawWorldModel(true)
		self.Pilot:Spawn()
		self.Pilot:SetNetworkedBool("isDriveShuttle",false)
		self.Pilot:SetPos(self.Entity:GetPos()+Vector(0,0,100))
	end

 	local effectdata = EffectData() 
 		effectdata:SetOrigin( self.Entity:GetPos() ) 
  	util.Effect( "Explosion", effectdata, true, true ) 
end

function ENT:OnTakeDamage(dmg)
	if DESTROYABLE then	
		self.life = self.life - dmg:GetDamage()
		if ( self.life < 1 ) then
			self.Entity:DoKill()
			self.Done=true
			self.Entity:Remove()
		end
	end
end

function ENT:OnRemove()
	if (self.isinuse>0) then
		self.Value = 0
		self.Pilot:UnSpectate()
		self.Pilot:DrawViewModel(true)
		self.Pilot:DrawWorldModel(true)
		self.Pilot:Spawn()
		self.Pilot:SetNetworkedBool("isDriveShuttle",false)
		self.Pilot:SetPos(self.Entity:GetPos()+Vector(0,0,100))
	end
	
	self.Entity:DoKill()
end

function ENT:Use(ply,caller)
	if not self.Inflight then
		self.isinuse = 1
		self.Entity:GetPhysicsObject():Wake()
		self.Entity:GetPhysicsObject():EnableMotion(true)
		self.Inflight=true
		self.Pilot=ply

		ply:Spectate( OBS_MODE_ROAMING )
		--ply:SpectateEntity( self.Entity )
		ply:DrawViewModel(false)
		ply:DrawWorldModel(false)
		ply:StripWeapons()
		ply:SetNetworkedBool("isDriveShuttle",true)
		ply:SetNetworkedEntity("Shuttle",self.Entity)
		
		if not FLAMETRAIL then return end
		self.Firee = ents.Create("env_fire_trail")
		if !self.Firee then return end
		self.Firee:SetKeyValue("spawnrate","3")
		self.Firee:SetKeyValue("firesprite","sprites/firetrail.spr" )
		self.Firee:SetPos(self.Entity:GetPos())
		self.Firee:SetParent(self.Entity)
		self.Firee:Spawn()
		self.Firee:Activate()
	end
end

function ENT:PreEntityCopy()
if (WireAddon == 1) then
	local DupeInfo = Wire_BuildDupeInfo(self.Entity)
	if DupeInfo then
		duplicator.StoreEntityModifier( self.Entity, "WireDupeInfo", DupeInfo )
	end
end
end

function ENT:PostEntityPaste( Player, Ent, CreatedEntities )
	if (WireAddon == 1) then
		if (Ent.EntityMods) and (Ent.EntityMods.WireDupeInfo) then
			Wire_ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, function(id) return CreatedEntities[id] end)
		end
	end
end
